﻿using System.Reflection;

namespace Foundation.Core
{
    internal class TypeSelectCollectionCreator : ISelectCollectionCreator
    {
        public TypeSelectCollectionCreator(SelectItemOptions options, SelectFilterRegistrar registrar)
        {
            Options = options;
            Registrar = registrar;
        }

        public SelectItemOptions Options { get; }

        public SelectFilterRegistrar Registrar { get; }

        public virtual Task<SelectCollection> CreateAsync(string key, SelectCategory category, IDictionary<string, object> arguments, CancellationToken cancellationToken)
        {
            var executors = Registrar.GetExecutors(category);

            var type = Options.ItemDeclaringType;
            var executor = executors.FirstOrDefault(f => f.CanHandle(type));

            if (executor == null)
            {
                throw new AppException($"[{key}],type[{type}] 未找到可用选项执行器");
            }

            var list = new List<ISelectItem>();

            var members = executor.GetMemberInfos(type);

            var model = executor.CreateModel(type);
            if (members != null)
            {
                foreach (var member in members)
                {
                    var context = new TypeSelectCreateExecuteContext(key, category, member, model);

                    executor.Execute(context);

                    if (context.Ignore) continue;

                    var value = (context.Value == null || (context.Value is string s && s.IsNullOrEmpty()))
                            ? (GetValue(member, model) ?? member.Name)
                            : context.Value;

                    var item = new TypeMemberSelectItem(member, context.Extend)
                    {
                        Name = context.Name.IsNullOrEmpty() ? member.Name : context.Name,
                        Label = context.Label.IsNullOrEmpty() ? member.Name : context.Label,
                        Value = value,
                    };

                    list.Add(item);
                }
            }

            var resultFilters = Registrar.GetResultFilters(category);

            if (resultFilters != null)
            {
                var resultContext = new SelectResultContext(key, category, list, type);
                foreach (var resultFilter in resultFilters)
                {
                    resultFilter.OnCreated(resultContext);
                }
            }

            return Task.FromResult(new SelectCollection(category, list));
        }

        protected object GetValue(MemberInfo info, object model)
        {
            if (info is FieldInfo f) return f.GetValue(model);
            else if (info is PropertyInfo p) return p.GetValue(model);

            throw new AppException($"{info.DeclaringType.FullName}.{info.Name},无法识别成员类型[{info.MemberType}]");
        }
    }
}
